BackTrader Strategy 交易策略
交易策略是回测的核心,在 BackTrader 中对应位 Strategy 类。在本文中记录了对 Strategy 类的介绍。
声明策略
按照如下方式声明策略:
import backtrader as bt
class TestStrategy(bt.Strategy):
pass
类初始化
进行初始化操作:
- 数据加工
- 状态声明
- 指标创建
示例代码:
def __init__(self):
# 数据加工
self.dataclose = self.datas[0].close
# 状态声明
self.order = None
self.buyprice = None
self.buycomm = None
# 指标创建
self.rsi = bt.indicators.RSI_SMA(self.datas[0], period=self.params.maperiod)
bt.indicators.ExponentialMovingAverage(self.datas[0], period=25)
bt.indicators.WeightedMovingAverage(self.datas[0], period=25, subplot=True)
bt.indicators.StochasticSlow(self.datas[0])
notify_order
该方法在执行买入卖出时会被回调。方法签名:
def notify_order(self, order):
其中 order 包含一系列状态:
状态 | 说明 |
---|---|
Submitted | |
Accepted | |
Completed | 交易完成 |
Canceled | |
Margin | |
Rejected |
其中,目前实际用到的只有 Completed 状态。
示例代码:
def notify_order(self, order):
if order.status in [order.Submitted, order.Accepted]:
# Buy/Sell order submitted/accepted to/by broker - Nothing to do
return
# 交易完成
# Attention: broker could reject order if not enough cash
if order.status in [order.Completed]:
if order.isbuy():
self.log(
"BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f"
% (order.executed.price, order.executed.value, order.executed.comm)
)
self.buyprice = order.executed.price # 买入价格
self.buycomm = order.executed.comm # 买入手续费
elif order.issell():
self.log(
"SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f"
% (order.executed.price, order.executed.value, order.executed.comm)
)
self.bar_executed = len(self) # 买入日期
elif order.status in [order.Canceled, order.Margin, order.Rejected]:
self.log("Order Canceled/Margin/Rejected")
# Write down: no pending order
self.order = None
notify_trade
该方法在一直股票清仓后会被回调。方法签名:
def notify_trade(self, trade):
示例代码,展示此次交易的利润:
def notify_trade(self, trade):
if not trade.isclosed:
return
self.log("OPERATION PROFIT, GROSS %.2f, NET %.2f" % (trade.pnl, trade.pnlcomm))
一个是扣手续费之前的利润,一个是实际到手的利润。
next
这是具体编写策略的位置。具体来说,根据股票数据,和指标,编写数学、逻辑算法,决定执行买入、卖出操作。
stop
策略定制回调。
self.datas 数据
在 Strategy 类中,通过 self.datas 访问股票数据。
self.datas 是由 Data Feed 传入的股票数据,data 表示一个数据表,datas 表示多个数据表。也就是说,在 BackTrader 中,允许向 Strategy 传入多个数据表(datas),而每个 data 表示一支股票的数据。
取第 N 个数据表
由于 self.datas 是数据表的合计,因此在实际数据获取时,需要从中取出某一个数据。BackTrader 支持通过索引进行获取:
# 支持两种写法
self.datas[0]
self.data0
self.data
在 BackTrader,也提供 self.data 属性,默认指向添加的第一组数据(第一个数据表)。
根据表名获取数据
在添加 Data Feed 时,可以指定一个名称(name)。
这样在获取时,也可以按表明进行获取。具体方法:
self.getdatabyname('dataname')